#include <iostream>

#if 0
    // 交换两个变量的值：指针（C语言的痛点）
    // 能否不用指针？
    // 如果不用指针，实参传形参的时候传的是值，而非地址，如果不传地址，形参不等于实参，就没有办法取修改外部变量
    // 所以基于这个，C++引入了一个全新的工具，用来替代指针————引用（C++特有的）
    void Swap(int *a, int *b)
    {
        int temp = *a;
        *a = *b;
        *b = temp;
    }

    int main()
    {
        int a =10;
        int b = 20;
        Swap(&a, &b);
        std::cout<<"a="<<a<<" b="<<b<<std::endl;
        return 0;
    }
#endif

#if 0
    int main()
    {
        // 引用：所代表的含义是变量的别名
        // 一定要初始化，引用不能单独出现单独定义（要用它的时候，就必须要让它指向一个已经存在的变量）
        int b = 10;
        int &a = b;  // 这句话的含义是：将a设置为b的引用，修改a就相当于b也被修改了
        a = 20;
        std::cout<<"b = "<<b<<std::endl;
        // &是引用符号，当它和数据类型一起出现的时候代表某个类型的引用，而不是取地址符
    }
#endif

#if 0
    int main()
    {
        int b = 10;
        int &a = b;
        int c = 30;
        // 引用一经定义，不会再修改朝向
        a = c;  // 把c的值给a，就相当于把c的值给b
        std::cout<<"b = "<<b<<std::endl;
        return 0;
    }
#endif

#if 0
    void Swap(int &a, int &b)
    {
        int temp = a;
        a = b;
        b = temp;
    }

    int main()
    {
        int a =10;
        int b = 20;
        Swap(a, b); // 引用就直接可以接变量本身
        std::cout<<"a="<<a<<" b="<<b<<std::endl;
        return 0;
    }
#endif

#if 0
    int main()
    {
        // 引用的本质就是指针常量：指针常量的两个特点和引用是一模一样的
        int a = 10; 
        int b = 20;
        // 指针常量：
        int* const p = &a;  // 1、不能单独定义，因为它不能赋别的值，所以它必须在初始化的时候进行定义，必须要赋初值   
        // p = &b; // 2、也不能指向别人
        return 0;
    }
#endif

#if 0
    void fun(int &a)
    {
        std::cout<<a<<std::endl;
    }

    int main()
    {
        // 左值引用
        int a = 10;
        fun(a);
        // fun(10); // 不能传常量，引用的本质是指针常量，所以它指向的东西首先得能够取地址和有内存，即它得是一个左值
        // int &b = 10; // 左值引用没有办法传递右值
        return 0;
    }
#endif

#if 0
    void fun(const int &a)
    {
        // a++; // 常引用不能修改，如果传const int &a那就意味着在这个函数里面a就不能动了  
        std::cout<<a<<std::endl;
    }

    int main()
    {
        // 常引用
        // 没法给一个常量放引用，因为它没内存，那就找一个没内存也能放引用的东西
        int a = 10;
        fun(10);
        // 加const关键字，传const引用，称为常量引用，简称常引用
        // const int &b = 10;
        // 引用常引用的原因：左值引用无法传递右值，常引用可以
        return 0;
    }
#endif

#if 0
    // 返回一个局部变量的引用
    int& func()
    {
        int a = 10;
        return a;
    }

    int main()
    {
        // 不允许返回一个局部变量的引用
        int &a = func();    
        return 0;
    }
#endif

#if 0
    // 如果返回值是常引用呢？
    const int& func()
    {
        int a = 10;
        return a;
    }

    int main()
    {
        // 函数返回一个常引用，不允许用一个普通左值引用去接
        // int &a = func();

        // 用常引用接也不可以
        // const int &a = func();

        // 一个局部变量，不管是返回它的引用还是常引用，它本质上都是去取的一个变量的值，但是这个变量是一个局部变量，局部变量只要取引用就相当于是取它的指针，一旦函数执行完毕，局部变量的内存空间就会被释放
        return 0;
    }
#endif

#if 1
    // 不管是引用还是常引用，都不能那样去写
    // 只要是局部变量返回引用，都不允许
    // 怎样才能允许呢？
    // 静态变量生命周期从程序开始到程序结束
    int& func()
    {
        static int a = 10;
        return a;
    }

    int main()
    {
        int &a = func();
        return 0;
    }
#endif


